package cn.gene.timeyan.article.webapi.service.impl;

import cn.gene.timeyan.article.service.ArticleService;
import cn.gene.timeyan.article.service.ReplyService;
import cn.gene.timeyan.article.webapi.mapper.CommentMapper;
import cn.gene.timeyan.article.webapi.mapper.ReplyMapper;
import cn.gene.timeyan.common.constant.RedisConstants;
import cn.gene.timeyan.common.exception.TimeyanServiceException;
import cn.gene.timeyan.common.restful.ResponseCode;
import cn.gene.timeyan.common.utils.FormUtils;
import cn.gene.timeyan.pojo.article.dto.ReplyDTO;
import cn.gene.timeyan.pojo.article.model.Reply;
import cn.gene.timeyan.pojo.article.vo.ReplyVO;
import cn.gene.timeyan.pojo.ums.vo.UserSimpleVO;
import cn.gene.timeyan.ums.service.IUserDetailService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 鏂囩珷璇勮?鐨勫洖澶 服务实现类
 * </p>
 *
 * @author LWG
 * @since 2022-07-25
 */
@Service
public class ReplyServiceImpl extends ServiceImpl<ReplyMapper, Reply> implements ReplyService {
    @Autowired
    private ReplyMapper replyMapper;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @DubboReference
    private IUserDetailService dubboUserDetails;
    private static final int PAGESIZE=20;
    private static final String MODEL="desc";

    /**
     * 添加回复
     * @param replyDTO
     */
    @Override
    public void addNew(ReplyDTO replyDTO) {
        //访问redis查看用户是否短时间内重复评论该贴
        String key= RedisConstants.ARTICLE_COMMENT+replyDTO.getArticleId()+":user:"+replyDTO.getRespondentId();
        if (redisTemplate.hasKey(key)){
            //存在就说明，用户频繁操作需要提醒
            throw new TimeyanServiceException(ResponseCode.ERR_UNKNOWN,"您评论的太快了，请等1分钟后再进行评论哟");
        }
        Reply reply=new Reply();
        BeanUtils.copyProperties(replyDTO, reply);
        //判断回复人和贴主是否为一个人
        Long authorId=articleService.getUserIdByArticleId(replyDTO.getArticleId());
        if (replyDTO.getRespondentId()==authorId)reply.setIsAuthor("1");
        else reply.setIsAuthor("0");
        //判断是否有该评论缓存
        String commentKey="article:"+replyDTO.getArticleId()+":commentDetail:"+replyDTO.getCommentId();
        int lines=replyMapper.addNewReply(reply);
        int rows=0;
        if(redisTemplate.hasKey(commentKey)){
            //有缓存，该评论回复数加一
            redisTemplate.opsForHash().increment(commentKey,"replys",1);
            rows=1;
        }else{
            //否则去修改数据库
            rows=commentMapper.updateReplyByCommentId(replyDTO.getCommentId());
        }
        //未频繁评论
        if (lines<1||rows<1){
            throw new TimeyanServiceException(ResponseCode.ERR_UNKNOWN,"系统繁忙，回复失败，请稍后重试");
        }
        //存过后保留记号,1分钟
        redisTemplate.opsForValue().set(key,1,1, TimeUnit.MINUTES);
    }

    /**
     * 获取回复列表
     * @param commentId
     * @param model
     * @param page
     * @return
     */
    @Override
    public List<ReplyVO> listByCommentId(Long commentId,String model,Integer page) {
        String key="comment:"+commentId+":reply";
        //是否有缓存
        if (!redisTemplate.hasKey(key)){
            //没有缓存
            //查询回复
            List<ReplyVO> replyVOS=replyMapper.listByCommentIdTime(commentId);
            //存到缓存的有序set中
            for (ReplyVO replyVO:replyVOS) {
                double time = FormUtils.parseTimeByLocalDateTime(replyVO.getReplyTime());
                redisTemplate.opsForZSet().add(key, replyVO.getArticleReplyId(), time);
                //将回复信息分为固定的和点赞数，方便增改
                Map<String, Object> map = new HashMap<>();
                map.put("commentInfo", JSON.toJSON(replyVO));
                map.put("likes", replyVO.getLikeNum());
                redisTemplate.opsForHash().putAll(key + ":detail:" + replyVO.getArticleReplyId(), map);
            }
            redisTemplate.expire(key,30,TimeUnit.MINUTES);
        }
        //获取有序集
        Set<Long> list;
        List<ReplyVO> replyVOS=new ArrayList<>();
        if (MODEL.equals(model)){
            //获取降序
            list= redisTemplate.opsForZSet().reverseRange(key,0,page*PAGESIZE-1);
        }else {
            //获取升序
            list = redisTemplate.opsForZSet().range(key, 0, page * PAGESIZE - 1);
        }
        //获取具体信息
        for (Object id:list){
            ReplyVO replyVO=JSON.parseObject(redisTemplate.opsForHash().get(key + ":detail:" + id,"commentInfo").toString(),ReplyVO.class);
            replyVO.setLikeNum((Integer) redisTemplate.opsForHash().get(key+":detail:"+id,"likes"));
            //获取回复人信息
            UserSimpleVO reply=dubboUserDetails.selectUserCommentVOByUserId(replyVO.getRespondentId());
            replyVO.setRespondentNickname(reply.getNickname());
            replyVO.setRespondentAvatar(reply.getAvatar());
            //获取受评论人信息
            UserSimpleVO byReply=dubboUserDetails.selectUserCommentVOByUserId(replyVO.getByRespondentId());
            replyVO.setByRespondentNickname(byReply.getNickname());
            replyVOS.add(replyVO);
            }
        return replyVOS;
    }

    /**
     * 设置某一条回复的显示
     * @param id
     */
    @Override
    public void display(Long id){
        int rows=replyMapper.display(id);
        if (rows<1){
            throw new TimeyanServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"设置失败，请稍后重试");
        }
    }
    /**
     * 设置某一条回复的隐藏
     * @param id
     */
    @Override
    public void hide(Long id) {
        int rows=replyMapper.hide(id);
        if (rows<1){
            throw new TimeyanServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"设置失败，请稍后重试");
        }
    }
}
